#pragma once 
#include "Thread.hpp"
#include "Lockguard.hpp"
#include <vector>
#include <queue>
#include <unistd.h>
#define THREAD_NUM 5
template<class T>
class ThreadPool
{
public://提供一批对外的接口
    static ThreadPool<T>* GetThreadpool(int num = THREAD_NUM)
    {
        if(threadpoolptr == nullptr)
        {
            Lockguard lock(&mutex);
            if(threadpoolptr == nullptr)
            {
                threadpoolptr = new ThreadPool<T>(num);
            }
        }
        return threadpoolptr;
    }
    pthread_mutex_t* Getmutex()
    {
        return &_mtx;
    }
    pthread_cond_t* Getcond()
    {
        return &_cond;
    }
    bool IsQueueEmpty()
    {
        return _queue_Task.empty();
    }
    void waitCond()
    {
        pthread_cond_wait(&_cond,&_mtx);
    }
    T GetTask()
    {
        T t = _queue_Task.front();
        _queue_Task.pop();
        return t;
    }
private:
    ThreadPool(int tem_num = THREAD_NUM)//构造函数的任务：构建num个线程对象
    :_num(tem_num)
    {
        pthread_mutex_init(&_mtx,nullptr);
        pthread_cond_init(&_cond,nullptr);
        for(int i = 1;i<=_num;i++)//创建了n个线程对象
        {
            thread* t = new thread(routine,i,this);
            _threads.push_back(t);
        }
    }
    ThreadPool(const ThreadPool<T>& others) = delete;
    ThreadPool<T>& operator=(const ThreadPool<T>& others) = delete;


    public:
        static void* routine(void* args)
    {
        threaddata* td = (threaddata*)args;
        ThreadPool<T>* tp = (ThreadPool<T>*)(td->_args);
        while(1)
        {
            T task;
            {
                Lockguard lock(tp->Getmutex());//自动加锁解锁
                //while(tp->IsQueueEmpty()) pthread_cond_wait(tp->Getcond(),tp->Getmutex());
                while(tp->IsQueueEmpty()) tp->waitCond();
                //走到这里说明队列中绝对有任务
                task = tp->GetTask();
            }
            cout<<td->_name<<"处理："<<task._x<<" + "<<task._y<<" = "<<task()<<endl;
        }
    }
    //需要一个让线程跑起来的函数
    void run()
    {
        for(auto &iter:_threads)
        {
            iter->start();
        }
    }
    void pushTask(const T& t)//向线程池里push任务
    {
        
        Lockguard lock(&_mtx);//自动上锁解锁
        _queue_Task.push(t);//向线程池里push
        pthread_cond_signal(&_cond);//发信号，提醒消费者线程可以来领取任务了
    }
    ~ThreadPool()
    {
        for(auto &iter:_threads)
        {
            iter->join();
            delete iter;
        }
        pthread_mutex_destroy(&_mtx);
        pthread_cond_destroy(&_cond);
    }
private:
    //需要一个线程数
    int _num;
    //不止需要一个线程，需要一个线程的vector列表
    vector<thread*> _threads;
    //需要一个“超市”也就是任务缓冲区
    queue<T> _queue_Task;
    //需要一把锁,该锁为生产者消费者所共享
    pthread_mutex_t _mtx;
    //需要一个条件变量,该条件变量为消费者线程共享
    pthread_cond_t _cond;

    //用于单例模式
    static ThreadPool<T>* threadpoolptr;
    static pthread_mutex_t mutex;
};

template<typename T>
ThreadPool<T>* ThreadPool<T>::threadpoolptr = nullptr;
template<typename T>
pthread_mutex_t ThreadPool<T>::mutex = PTHREAD_MUTEX_INITIALIZER;